package foot.servlet;

import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Collection;
import java.util.Formatter;
import java.util.HashSet;
import java.util.List;

import javax.ejb.EJB;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import foot.modele.Arbitre;
import foot.modele.Equipe;
import foot.modele.Joueur;
import foot.modele.Match;
import foot.stateless.ITournoi;
import foot.stateless.ITournoi.etat;
import foot.stateless.TournoiLocal;

/**
 * Servlet implementation class FootServlet
 */
@WebServlet("/FootServlet")
public class FootServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	@EJB
	private TournoiLocal _tournoi;
	/**
	 * @see HttpServlet#HttpServlet()
	 */
	public FootServlet() {
		super();

	}

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doPost(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		HttpSession session = request.getSession(true);
		ITournoi facade = (ITournoi) session
				.getAttribute("mafacade");
		if (facade == null) {
			Context ctx;
			try {
				ctx = new InitialContext();
				facade = (ITournoi) ctx
						.lookup("java:global/footMassonMonedierePerrin/footMassonMonedierePerrinEJB/TournoiBeanFacade!foot.stateless.TournoiLocal");

			} catch (NamingException e) {
				e.printStackTrace();
			}
			session.setAttribute("mafacade", facade);
		}
		//on retire l'attribut d'erreur
		session.setAttribute("erreur", null);
		//on rajoute ne session l'état du tornoi
		session.setAttribute("etat", etat.toInt(facade.getEtat()));
		//on recupère les équipes
		Collection<Equipe> lesequipes = facade.getToutesLesEquipes();
		//session.setAttribute("equipes", lesequipes);
		String action = request.getParameter("action");
		if(action == null || action.equals("accueil")){
			//lesequipes = facade.getToutesLesEquipes();
			session.setAttribute("equipes", lesequipes);
			//TODO remove
			//<DEBUG>
			for(Equipe e : lesequipes)
			{
				System.out.println("equipe : "+ e.getNomEquipe() + "nb joueur : "+ e.getLesJoueurs().size());
				for(Joueur j : e.getLesJoueurs())
					System.out.println("nom : "+j.getNom()+"prenom : "+j.getPrenom());
			}
			//</DEBUG>
			Match racine = _tournoi.getMatchRacine();
			session.setAttribute("match", racine);
			lesequipes = null;
			request.getRequestDispatcher("/accueil.jsp").forward(request, response);
		}
		else if(action.equalsIgnoreCase("admin")){
			//connexion administrateur
			request.getRequestDispatcher("/adminConnect.jsp").forward(request, response);

		}

		else if(action.equals("deconnexion")){
			//deconnexion administrateur
			deconnexion(request,response);
		}
		else if(action.equalsIgnoreCase("Inscrire")){
			//on vérifie que le tournoi n'est pas deja lancé, sinon , on ne peux ajouter d'équipes dedans
			if(facade.getEtat().equals(ITournoi.etat.INSCRIPTION))
			{
				//gerer le rajout d'une équipe
				request.getRequestDispatcher("/inscrireEquipe.jsp").forward(request, response);
			}
			else
			{
				String error = "Nous somme désolé mais les inscriptions des équipes sont terminés";
				Error(error, request, response);
			}
		}
		else if(action.equalsIgnoreCase("connexionAdmin")){
			//on vérifie le mot de passe et le log admin
			String admlog = request.getParameter("admlog");
			String admpassword = request.getParameter("admpasswd");
			if(!facade.login(admlog, admpassword)){
				Error("le couple login / mot de passe est incorrect", request, response);
			}
			else{
				//stockage des information necessaire
				session.setAttribute("equipes", _tournoi.getToutesLesEquipes());
				session.setAttribute("arbitres", _tournoi.getTousLesArbitres());
				session.setAttribute("isAdmin", true);
				//co admin reussi
				session.setAttribute("equipes", _tournoi.getToutesLesEquipes());
				session.setAttribute("arbitres", _tournoi.getTousLesArbitres());
				session.setAttribute("genA", _tournoi.getGenA());
				session.setAttribute("genE", _tournoi.getGenE());
				request.getRequestDispatcher("/menuadmin.jsp").forward(request, response);
			}

		}
		else if(action.equalsIgnoreCase("listeEquipe")){
			//on recupère les équipes depuis la facade
			lesequipes = facade.getToutesLesEquipes();
			//on les ajoute en session
			session.setAttribute("equipes", lesequipes);
			request.getRequestDispatcher("/toutesEquipes.jsp").forward(request, response);
		}
		else if(action.equalsIgnoreCase("detailequipe")){
			//on veux récupérer les détails de l'équipe
			int id = Integer.parseInt(request.getParameter("lequipe"));
			Equipe e = facade.getEquipeAvecId(id);
			session.setAttribute("labonneequipe", e);
			request.getRequestDispatcher("/detailEquipe.jsp").forward(request, response);
		}
		else if(action.equalsIgnoreCase("retourMenuAdmin")){
			//l'administrateur retourne à sa page d'accueil
			Boolean isAdmin = (Boolean) session.getAttribute("isAdmin");
			if( isAdmin != null && isAdmin ==true){
				//on recupère les informations utiles à la jsp
				//et on les ajoute à la session
				session.setAttribute("equipes", _tournoi.getToutesLesEquipes());
				session.setAttribute("arbitres", _tournoi.getTousLesArbitres());
				session.setAttribute("genA", _tournoi.getGenA());
				session.setAttribute("genE", _tournoi.getGenE());
				request.getRequestDispatcher("/menuadmin.jsp").forward(request, response);
			}
			else{
				//si probleme, retourne à l'accueil
				request.getRequestDispatcher("/accueil.jsp").forward(request, response);
			}
		}
		//inscription équipe
		else if(action.equalsIgnoreCase("valideEquipe")){
			if(facade.getEtat().equals(etat.INSCRIPTION)){
				//on recupère les informations relatives à l'inscription d'une équipe
				//à savoir : les noms, prenoms, etc...
				String nomEquipe = request.getParameter("nomEquipe");
				String[] lesNoms = request.getParameterValues("Nomjoueur");
				String[] lesPrenoms = request.getParameterValues("Prenomjoueur");
				//appel à la facade pour enregistrer l'équipe
				facade.inscrireEquipe(nomEquipe, lesNoms, lesPrenoms);
				//on récupère toutes les équipes pour recharger l'accueil à jour
				lesequipes = facade.getToutesLesEquipes();
				session.setAttribute("equipes", lesequipes);
				request.getRequestDispatcher("/accueil.jsp").forward(request, response);
			}
			else
			{
				String error = "Nous somme désolé mais les inscriptions des équipes sont terminés";
				Error(error,request,response);
			}

		}
		else if(action.equalsIgnoreCase("ajoutearbitreadmin")){
			//l'arbitre rajoute un arbitre, ou plusieurs
			Boolean isAdmin = (Boolean) session.getAttribute("isAdmin");
			if(isAdmin && isAdmin != null){
				//on l'envoie sur la bonne jsp
				request.getRequestDispatcher("/admsaisiearbitre.jsp").forward(request, response);
			}
			else{
				Error("Vous ne pouvez pas rajouter d'arbitre. Veuillez vous connectez en administrateur", request, response);
			}
		}
		//inscrire arbitre
		else if(action.equalsIgnoreCase("validearbitre")){
			//on veux valider l'inscription d'arbitre(s)
			Boolean isAdmin = (Boolean) session.getAttribute("isAdmin");
			if(isAdmin && isAdmin != null){
				//on est admin

				//on recupère tous les noms/prenoms
				String[] lesNoms = request.getParameterValues("NomArbitre");
				String[] lesPrenoms = request.getParameterValues("PrenomArbitre");
				if(lesNoms != null && lesPrenoms != null && lesNoms.length!=0 && lesPrenoms.length != 0)
					//si on a pas rentrer autant de noms que de prenoms (normalement les champs required de la jsp s'en assure deja)
					//on appele la facade pour terminer l'inscription
					facade.inscrireArbitres(lesNoms,lesPrenoms);

				//on recupère les arbitres pour mettre a jour le menu administration
				Collection<Arbitre> lesArbitres = facade.getTousLesArbitres();
				session.setAttribute("arbitres", lesArbitres);
				session.setAttribute("equipes", _tournoi.getToutesLesEquipes());
				session.setAttribute("arbitres", _tournoi.getTousLesArbitres());
				session.setAttribute("genA", _tournoi.getGenA());
				session.setAttribute("genE", _tournoi.getGenE());
				request.getRequestDispatcher("/menuadmin.jsp").forward(request, response);
			}
			else{
				session.setAttribute("isAdmin", false);
				Error("Vous n'etes pas Admin, vous ne pouvez pas ajouter d'arbitre", request, response);
			}
		}
		else if(action.equalsIgnoreCase("affectarbitre")){
			//on va affecter les arbitres au matchs

			//verifier que l'on est bien administration
			Boolean isAdmin = (Boolean) session.getAttribute("isAdmin");
			if(isAdmin != null && isAdmin){

				//on recupère le sinformations
				Collection<Arbitre> lesArbitres = facade.getTousLesArbitres();
				Collection<Match> lesMatchs = facade.MatchsSansArbitre();
				//on ajoute dans la session
				session.setAttribute("lesMatchs", lesMatchs);
				session.setAttribute("lesArbitres", lesArbitres);
				//on envoie sur la jsp
				request.getRequestDispatcher("/affectArbitre.jsp").forward(request, response);
			}
			else{
				Error("Vous ne pouvez pas affecter les Arbitres. Veuillez vous connecter", request, response);
			}
		}
		else if(action.equals("AjoutBut")) {
			ajoutBut(request, response);
		}
		else if(action.equals("valideAffectArbitre")){
			affectationArbitre(request,response);
		}
		else if(action.equals("modifmatch")){
			modifMatch(request,response);
		}
		else if(action.equals("endgame")) {
			changeEtatMatch(request, response);
		}
		else if(action.equals("detailmatch")) {
			//on vérfie l'id du match
			Match m = _tournoi.getMatchAvecId(Integer.parseInt(request.getParameter("idmatch")));
			if(m != null)
			{
				//récupération des informations
				session.setAttribute("leMatch", m);
				session.setAttribute("score", m.score());
				//redirection vers la jsp
				request.getRequestDispatcher("/detailMatch.jsp").forward(request, response);
			}
			else
			{
				Error("Le match demandé n'existe pas", request, response);
			}
		}
		else if(action.equals("modifierMatchs")) {
			//on vérifie que l'on est admin
			Boolean isAdmin = (Boolean) session.getAttribute("isAdmin");
			if(isAdmin != null && isAdmin) {
				//on récupère grace à la facade les matchs en cours
				Collection<Match> listeMatchs = _tournoi.getTousLesMatchsEnCours();
				session.setAttribute("listeMatch", listeMatchs);
				//on affecte en session et on envoie sur la jsp
				request.getRequestDispatcher("/listeMatchs.jsp").forward(request, response);
			}
			else{
				Error("Vous ne pouvez pas modifier les matchs", request, response);
			}
		}
		else if(action.equals("genArbitres")) {
			//on va vérifier que l'on ets admin, et on va générer un set d'exemple d'arbitre
			Boolean isAdmin = (Boolean) session.getAttribute("isAdmin");
			if(isAdmin != null && isAdmin) {
				//la facade génère les données
				_tournoi.peuplerArbitre();
				//on récupère la base a jour depuis la facade
				Collection<Arbitre> listeArbitre = _tournoi.getTousLesArbitres();
				session.setAttribute("arbitres", listeArbitre);
				session.setAttribute("equipes", _tournoi.getToutesLesEquipes());
				session.setAttribute("arbitres", _tournoi.getTousLesArbitres());
				session.setAttribute("genA", _tournoi.getGenA());
				session.setAttribute("genE", _tournoi.getGenE());
				//on ajoute en session , et on evoie sur la jsp
				request.getRequestDispatcher("/menuadmin.jsp").forward(request, response);
			}
			else {
				String error = "Nous somme désolé la page demandée n'existe pas";
				Error(error, request, response);
			}
		}
		else if(action.equals("genEquipes")) {
			//idem que pour gen arbitre, mais pour les équipes
			Boolean isAdmin = (Boolean) session.getAttribute("isAdmin");
			if(isAdmin != null && isAdmin) {
				_tournoi.peuplerEquipe();
				Collection<Equipe> listeEquipe = _tournoi.getToutesLesEquipes();
				session.setAttribute("equipes", listeEquipe);
				session.setAttribute("equipes", _tournoi.getToutesLesEquipes());
				session.setAttribute("arbitres", _tournoi.getTousLesArbitres());
				session.setAttribute("genA", _tournoi.getGenA());
				session.setAttribute("genE", _tournoi.getGenE());
				request.getRequestDispatcher("/menuadmin.jsp").forward(request, response);
			}
			else {
				String error = "Nous somme désolé la page demandée n'existe pas";
				Error(error, request, response);				
			}
		}
		else if(action.equals("genTournoi")) {
			//on va générer les tours du tournoi

			//on vérifie que l'on est admin
			Boolean isAdmin = (Boolean) session.getAttribute("isAdmin");
			if(isAdmin != null && isAdmin) {
				//la facade génère les tours
				_tournoi.genererTours();
				//recupération des données, ajout en session
				session.setAttribute("etat", etat.toInt(_tournoi.getEtat()));
				session.setAttribute("match", _tournoi.getMatchRacine());
				session.setAttribute("equipes", _tournoi.getToutesLesEquipes());
				session.setAttribute("arbitres", _tournoi.getTousLesArbitres());
				session.setAttribute("genA", _tournoi.getGenA());
				session.setAttribute("genE", _tournoi.getGenE());
				//retour au menu admin
				request.getRequestDispatcher("/menuadmin.jsp").forward(request, response);
			}
			else {
				String error = "Nous somme désolé la page demandée n'existe pas";
				Error(error, request, response);				
			}
		}
		else if(action.equals("demTournoi")) {
			//on va démarer le tournoi
			Boolean isAdmin = (Boolean) session.getAttribute("isAdmin");
			if(isAdmin != null && isAdmin) {
				//on ets admin
				if(_tournoi.MatchsSansArbitre().isEmpty()) {
					//on change l'état du tournoi
					facade.setEtat(etat.ENCOURS);
					session.setAttribute("etat", etat.toInt(_tournoi.getEtat()));	
					session.setAttribute("equipes", _tournoi.getToutesLesEquipes());
					session.setAttribute("arbitres", _tournoi.getTousLesArbitres());
					session.setAttribute("genA", _tournoi.getGenA());
					session.setAttribute("genE", _tournoi.getGenE());
					request.getRequestDispatcher("/menuadmin.jsp").forward(request, response);
				}
				else{
					Error("Il reste des matchs sans arbitre, nous ne pouvons pas démarrer le tournoi", request, response); 
				}

			}
			else {
				String error = "Nous somme désolé la page demandée n'existe pas";
				Error(error, request, response);				
			}

		}

	}

	private void affectationArbitre(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		HttpSession s = request.getSession();

		//on va affecter les arbitres aux matchs
		String[] listeSelect = request.getParameterValues("select");
		if(listeSelect != null){
			// on vérifie que la liste des choisis n'est pas null
			List<Arbitre> listeArbitre = (List<Arbitre>) s.getAttribute("lesArbitres");
			Collection<Match> listeMatch = (Collection<Match>) s.getAttribute("lesMatchs");
			//on vérifie que l'on a autant de matchs que d'arbitres selectionnés pour les matchs
			if(listeArbitre != null && listeMatch != null && listeSelect.length == listeMatch.size())
			{
				int i=0;
				for(Match m : listeMatch)
				{
					int select = Integer.parseInt(listeSelect[i]);
					//on recupère l'arbitre avec son di auprès de la facade
					Arbitre selected = _tournoi.getArbitreAvecID(select);
					//la facade affecte l'arbitre au match
					_tournoi.affecterArbitreAMatch(selected, m);
					i++;
				}

				request.getRequestDispatcher("/menuadmin.jsp").forward(request, response);
			}
			else
			{
				String error;
				if(listeSelect.length == listeMatch.size())
				{
					error = "impossible de d(affecter les arbitres : certains match n'ont pas d'arbitre!";
				}
				else
				{
					error = "Nous somme désolè une erreur est survenue lors de la récupération de données";
				}
				Error(error, request, response);
			}
		}
		else{
			String error = "Nous somme désolè une erreur est survenue lors de la récupération de données";
			Error(error, request, response);
		}
	}

	private void modifMatch(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		HttpSession s = request.getSession();
		//recherche id du match a modifier & recuperation du match
		if(request.getParameter("id") != null)
		{
			int id = Integer.parseInt(request.getParameter("id"));


			Match match = _tournoi.getMatchAvecId(id);
			//ajout variable session
			if(match == null){
				Error("Le match n'existe pas", request, response);
			}
			else{


				s.setAttribute("leMatch", match);
				Boolean isAdmin = (Boolean) s.getAttribute("isAdmin");
				//verification role==admin
				if(isAdmin != null && isAdmin)
				{
					//on verifie que le match est programmee
					if(match.getEquipe1() != null && match.getEquipe2() != null && match.getArbitre() != null)
					{
						Collection<Joueur> listejoueurs= new HashSet<>();
						listejoueurs.addAll(match.getEquipe1().getLesJoueurs());
						listejoueurs.addAll(match.getEquipe2().getLesJoueurs());
						s.setAttribute("listejoueur", listejoueurs);
						request.getRequestDispatcher("/modifmatch.jsp").forward(request, response);
					}
					else
					{
						Error("Le match n'est pas complet, vous ne pouvez pas le modifier", request , response); 
					}
				}
				else
				{
					//role != admin
					//petit mensonge
					String error = "Nous somme désolé la page n'existe pas ";
					Error(error, request, response);
				}
			}
		}
		else
		{
			String error="Erreur lors de la récupération des données ";
			Error(error, request, response);
		}

	}

	private void deconnexion(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		HttpSession s = request.getSession();
		//retrait des variables admin
		s.removeAttribute("isAdmin");
		//retrait des variables arbitre
		s.removeAttribute("IsArbitre");
		s.removeAttribute("listeMatch");
		s.removeAttribute("currentUser");
		//		s.setAttribute("match", _tournoi.getMatchRacine());
		request.getRequestDispatcher("/accueil.jsp").forward(request, response);
	}

	private void ajoutBut(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		HttpSession s = request.getSession();
		Boolean isAdmin = (Boolean) s.getAttribute("isAdmin");
		if(isAdmin != null && isAdmin) {
			//récuperation des informations du but
			String joueur = request.getParameter("ButAuteur");
			String heure = request.getParameter("ButHeure");
			String tir_au_but = request.getParameter("tir_au_but");
			Match m = (Match)s.getAttribute("leMatch");
			if(joueur != null && m != null) {
				Joueur j = _tournoi.getJoueurWithId(Integer.parseInt(joueur));
				if(m.isTirsAuButs() && tir_au_but != null && tir_au_but.equals("on"))
					_tournoi.ajouterButAMatch(m, j, "", true);
				else if(m.isProlongation() && !heure.equals("") && Integer.parseInt(heure) >= 90 && Integer.parseInt(heure) <= 120)
					_tournoi.ajouterButAMatch(m, j, heure, false);
				else if(!heure.equals("") && Integer.parseInt(heure) <= 90 && !m.isProlongation() && !m.isTirsAuButs())
					_tournoi.ajouterButAMatch(m, j, heure, false);
			}

			request.getRequestDispatcher("/modifmatch.jsp").forward(request, response);		
		}
		else {
			//tentative d'accès direct a la page => retour a l'accueil
			//petit mensonge
			String error = "Nous somme désolé la page demandé n'existe pas";
			Error(error, request, response);
		}
	}

	private void changeEtatMatch(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		//on recupère la session
		HttpSession s = request.getSession();
		//on chercher si l'utilisateur est admin
		Boolean isAdmin = (Boolean) s.getAttribute("isAdmin");
		//on récupère le match
		Match m = (Match)s.getAttribute("leMatch");
		if(isAdmin != null && isAdmin && m != null) {
			if(!m.isProlongation() && !m.isTirsAuButs()) {
				//si on est dans le temps normal du match
				if(m.vainqueur() != null) {
					//la facade valide le match et le fait passer en prolongation 
					_tournoi.validerMatch(m);
					//on met a jour le tournoi
					_tournoi.MAJMatch();
					//on chnage le status du match
					m.setStatusMatch("match terminé");
				}
				else {
					//on afficheras les prolongation dans la jsp
					m.setProlongation(true);
					//on chnage le status
					m.setStatusMatch("Prolongation en cours");
				}
			}
			else if(m.isProlongation()) {
				if(m.vainqueur() != null) {
					//il n'y a pas match nul
					_tournoi.validerMatch(m);
					_tournoi.MAJMatch();
					m.setStatusMatch("match terminé");
				}
				else {
					//on passe aux tirs aux buts
					m.setStatusMatch("Tirs au but en cours");
					m.setTirsAuButs(true);
				}

			}
			else if(m.isTirsAuButs() && m.vainqueur() != null) {
				_tournoi.validerMatch(m);
				_tournoi.MAJMatch();
				//on cloture le match
				m.setStatusMatch("match terminé");
			}
			//on remet a jour ces matchs et on redirige
			Collection<Match> listeMatch =  _tournoi.getTousLesMatchsEnCours();
			s.setAttribute("listeMatch", listeMatch);			
			request.getRequestDispatcher("/listeMatchs.jsp").forward(request, response);
		}
		else {
			//tentative d'accès direct a la page => retour a l'accueil
			request.getRequestDispatcher("/accueil.jsp").forward(request, response);						
		}
	}


	/*
	 * petit fonction pour traiter les erreurs
	 */
	private void Error(String erreur,HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException 
			{
		//ajout de la variable session
		HttpSession s = request .getSession();
		s.setAttribute("error", erreur);
		//redirection
		request.getRequestDispatcher("/Error.jsp").forward(request, response);
			}

}
